﻿#light

// inc powerpack in f# interactive
#if COMPILED
#else
#r "FSharp.PowerPack.dll" 
#endif

// print a sequence
// |> Seq.iter (fun (x) -> printfn "%A" x) ;;


// piplining
// let (|>) x f = f x
// forward composition
// let (>>) f g x = g(f(x))
//
// example of use of forward composition (shorter syntax than use of pipeline)
let l = [1..10]
let mapFilter l = l |> List.map (fun x -> x * x) |> List.filter (fun x -> x % 2 = 0)
let mapFilter2 = List.map (fun x -> x * x) >> List.filter (fun x -> x % 2 = 0)
mapFilter2 [1..10] |> print_any


// Factorial
let rec fact x = if x <= 1 then 1 else x * fact (x-1) 
// nth Fibonacci Number
let rec fib n = if n <= 1 then n else fib (n-1) + fib (n-2)    


//primes experiments
open System.Collections

let getPrimes1 max =
    let primes = new BitArray(max+1, true)
    let max = max |> uint64
    let rec next_prime n results = 
        if (n>max) then results
        else if (primes.[int n]) then
            let start = n*n
            if start < max then
                let i = ref (int start)
                while !i < int max do 
                    primes.[!i] <- false
                    i := !i + int n
            next_prime (n+1UL) (n::results)
        else next_prime (n+1UL) results
    next_prime 2UL []
    
let getPrimes2 max = 
  let primes = new BitArray(max+1, true)
  seq { 2 .. max } |>
  Seq.filter (fun n -> 
    if primes.[n] then
      for i in int64 n * int64 n..int64 n..int64 max do primes.[int i] <- false
    primes.[n])
    
let getPrimes3 max = 
    let primes = new BitArray(max+1, true)
    [ for n in 2..max do
            if primes.[int n] then
                for i in int64 n * int64 n..int64 n..int64 max do primes.[int i] <- false
                yield n ]
    
let getPrimes4 max = 
    let primes = new BitArray(max+1, true)
    let result = new ResizeArray<int>(max/10)
    for n = 2 to max do
        if primes.[n] then
            let start = (int64 n * int64 n)
            if start < int64 max then
                let i = ref (int start)
                while !i < max do primes.[!i] <- false; i := !i + n
            result.Add n
    result
                          
let solve3 () = 
    getPrimes3 2000000 |> Seq.fold (fun acc itm -> int64 itm + acc) 0L     